package com.example.config;
import com.alibaba.cloud.commons.lang.StringUtils;
import lombok.AllArgsConstructor;
import lombok.Data;
import lombok.NoArgsConstructor;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.cloud.gateway.filter.GatewayFilter;
import org.springframework.cloud.gateway.filter.factory.AbstractGatewayFilterFactory;
import org.springframework.http.HttpHeaders;
import org.springframework.http.HttpStatus;
import org.springframework.http.server.reactive.ServerHttpRequest;
import org.springframework.http.server.reactive.ServerHttpResponse;
import org.springframework.stereotype.Component;
import org.springframework.util.Assert;
import java.util.Arrays;
import java.util.List;

/**
 * @program: tenghuawei-demo
 * @author: tenghw
 * @create: 2024-06-27 16:45
 * @Version 1.0
 * @description: 模拟授权的token验证，具体逻辑根据业务完善；自定义gateway的局部过滤器，名称必须是xxxGatewayFilterFactory格式
 *  */
@Component
@Slf4j
public class AuthorizeGatewayFilterFactory extends AbstractGatewayFilterFactory<AuthorizeGatewayFilterFactory.Config> {
    private static final String AUTHORIZE_TOKEN = "token";

    //读取bootstarp.yml或application.yml中配置文件中的参数Authorize ，将参数赋值到 配置类中
    @Value("${gateway.filter-settings.authorize-enabled:false}")
    private String authorizeEnabled;

    //构造函数，加载Config
    public AuthorizeGatewayFilterFactory() {
        //固定写法
        super(AuthorizeGatewayFilterFactory.Config.class);
        //log.info("authorize是否鉴权：{}", authorizeEnabled);//null
        log.info("Loaded GatewayFilterFactory [Authorize]");
    }

    @Override
    public List<String> shortcutFieldOrder() {
        log.info("authorize是否鉴权：{}", authorizeEnabled);
        // 验证给定的布尔表达式是否为true。如果表达式的值为false，则断言失败，通常会导致测试失败并抛出一个异常
        Assert.isTrue(Boolean.parseBoolean(authorizeEnabled), "authorizeEnabled is false");
        return Arrays.asList("enabled");
    }

    @Override
    public GatewayFilter apply(AuthorizeGatewayFilterFactory.Config config) {
        return (exchange, chain) -> {
            // 若不需要开启授权验证，直接放行
            if (!config.isEnabled()) {
                return chain.filter(exchange);
            }

            ServerHttpRequest request = exchange.getRequest();
            HttpHeaders headers = request.getHeaders();
            //从请求头中获取token
            String token = headers.getFirst(AUTHORIZE_TOKEN);
            if (token == null) {
                //从请求头参数中获取token
                token = request.getQueryParams().getFirst(AUTHORIZE_TOKEN);
            }

            ServerHttpResponse response = exchange.getResponse();
            //如果token为空，直接返回401，未授权
            if (StringUtils.isEmpty(token)) {
                response.setStatusCode(HttpStatus.UNAUTHORIZED);
                //处理完成，直接拦截，不再进行下去
                return response.setComplete();
            }
            /**
             * chain.filter().then(
             *  过滤器的后置处理...........
             * )
             */
            //授权正常，继续下一个过滤器链的调用
            return chain.filter(exchange);
        };
    }

    @Data
    @AllArgsConstructor
    @NoArgsConstructor
    public static class Config {
        // 控制是否开启认证
        private boolean enabled;
    }
}